package com.wxapp.admin.service.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wxapp.admin.api.pojo.entity.MenuDO;
import com.wxapp.admin.api.pojo.entity.RoleMenuDO;
import com.wxapp.admin.api.pojo.vm.menu.PMenuBaseVm;
import com.wxapp.admin.api.pojo.vm.menu.PMenuSelectVm;
import com.wxapp.admin.api.pojo.vm.menu.PMenuTreeSelectVm;
import com.wxapp.admin.api.pojo.vm.menu.PMenuTreeVm;
import com.wxapp.admin.api.pojo.vo.menu.QAddMenuVo;
import com.wxapp.admin.api.pojo.vo.menu.QMenuListVo;
import com.wxapp.admin.api.pojo.vo.menu.QMenuUpdateVo;
import com.wxapp.admin.service.mapper.MenuMapper;
import com.wxapp.admin.service.mapper.RoleMenuMapper;
import com.wxapp.admin.service.service.MenuService;
import com.wxapp.common.constant.base.IBaseService;
import com.wxapp.common.constant.pojo.vm.ResultVm;
import com.wxapp.common.constant.pojo.vo.UserVo;
import com.wxapp.common.constant.properties.WhiteRoleProperties;
import com.wxapp.common.core.annotation.DelCatch;
import com.wxapp.common.core.annotation.GetCatch;
import com.wxapp.common.util.check.CheckUtil;
import com.wxapp.common.util.copy.CopyUtil;
import com.wxapp.common.util.menuTree.TreeUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @author lgl
 */
@Service
@RequiredArgsConstructor
public class MenuServiceImpl extends IBaseService implements MenuService {
    private final MenuMapper menuMapper;
    private final RoleMenuMapper roleMenuMapper;
    private final WhiteRoleProperties whiteRoleProperties;
    @Override
    @GetCatch(key = "'MENU:'.concat(#userVo.id)")
    public ResultVm<List<PMenuTreeVm>> menu(UserVo userVo) {
        List<String> roles = menuMapper.getRoles(userVo.getId());
        if (whiteRoleProperties.getList().stream().anyMatch(roles::contains)) {
            userVo = null;
        }
       return success(getMenuTree(userVo,new QMenuListVo()));
    }

    @Override
    public ResultVm<List<PMenuTreeVm>> listMenu(QMenuListVo qMenuListVo) {
        return success( getMenuTree(null, qMenuListVo));
    }

    @Override
    @DelCatch(key = "'MENU:'.concat(#userVo.id)")
    public ResultVm<String> addMenu(UserVo userVo, QAddMenuVo qaddMenuVo) {
        LambdaQueryWrapper<MenuDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(MenuDO::getMenuType, qaddMenuVo.getMenuType()).eq(MenuDO::getName, qaddMenuVo.getName()).eq(MenuDO::getStatus, true);
        int count = Math.toIntExact(menuMapper.selectCount(wrapper));
        if (count > 0) {
            return error("菜单已存在");
        }
        var wxappMenuDO = CopyUtil.copyObjectNew(qaddMenuVo, MenuDO::new, (s, r) -> {
            r.setStatus(true);
            r.setDisplay(true);
            return null;
        });
        menuMapper.insert(wxappMenuDO);
        return success();
    }

    @Override
    @DelCatch(key = "'MENU:'.concat(#userVo.id)")
    public ResultVm<String> updateMenu(UserVo userVo, QMenuUpdateVo qUpdateVm) {
        var wxappMenuDO = menuMapper.selectById(qUpdateVm.getId());
        if (CheckUtil.isNullObject(wxappMenuDO)) {
            return error("没有找到菜单信息");
        }
        CopyUtil.copyObject(qUpdateVm, wxappMenuDO, null);
        menuMapper.updateById(wxappMenuDO);
        return success();
    }

    @Override
    public ResultVm<PMenuBaseVm> detailMenu(String id) {
        var wxappMenuDO = menuMapper.selectById(id);
        if (CheckUtil.isNullObject(wxappMenuDO)) {
            return error("没有找到菜单信息");
        }
        return success(CopyUtil.copyObjectNew(wxappMenuDO, PMenuBaseVm::new, null));
    }

    @Override
    @DelCatch(key = "'MENU:'.concat(#userVo.id)")
    public ResultVm<String> deleteMenu(UserVo userVo, String id) {
        var wxappMenuDO = menuMapper.selectById(id);
        if (CheckUtil.isNullObject(wxappMenuDO)) {
            return error("没有找到菜单信息");
        }
        LambdaQueryWrapper<MenuDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(MenuDO::getPid, id).eq(MenuDO::getStatus, true);
        var wxappMenuDOS = menuMapper.selectList(wrapper);
        if (CheckUtil.isNotNullList(wxappMenuDOS)) {
            wxappMenuDOS.forEach(s -> s.setStatus(false));
            menuMapper.batchSaveOrUpdate(wxappMenuDOS);
        }
        wxappMenuDO.setStatus(false);
        menuMapper.updateById(wxappMenuDO);
        return success("更新成功");
    }

    @Override
    public ResultVm<List<PMenuSelectVm>> selectMenu(String name, String type) {
        LambdaQueryWrapper<MenuDO> query = new LambdaQueryWrapper<>();
        query.like(CheckUtil.isNotNullString(name), MenuDO::getName, name).eq(MenuDO::getMenuType, type).eq(MenuDO::getStatus, true).select(MenuDO::getId, MenuDO::getPid, MenuDO::getName);
        var menuList = menuMapper.selectList(query);
        var copyMenu = CopyUtil.copyListNew(menuList, PMenuSelectVm::new, null);
        return success(copyMenu);
    }

    @Override
    public ResultVm<List<PMenuTreeSelectVm>> treeSelect(String name, String type, String roleId) {
        LambdaQueryWrapper<MenuDO> query = new LambdaQueryWrapper<>();
        query.like(CheckUtil.isNotNullString(name), MenuDO::getName, name)
                .eq(CheckUtil.isNotNullString(type), MenuDO::getMenuType, type)
                .eq(MenuDO::getStatus, true)
                .select(MenuDO::getId, MenuDO::getPid, MenuDO::getName)
                .orderByDesc(MenuDO::getOrderNum);
        List<RoleMenuDO> roleMenuDOS = new ArrayList<>();
        if (CheckUtil.isNotNullObject(roleId)) {
            LambdaQueryWrapper<RoleMenuDO> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(RoleMenuDO::getRoleId, roleId);
            wrapper.eq(RoleMenuDO::getStatus, true);
            roleMenuDOS = roleMenuMapper.selectList(wrapper);
        }
        var menuList = menuMapper.selectList(query);
        List<RoleMenuDO> finalRoleMenuDOS = roleMenuDOS;
        List<PMenuTreeSelectVm> iBaseMenuTrees = TreeUtil.buildCopyTree(menuList, PMenuTreeSelectVm::new, (s, r) -> {
            if (CheckUtil.isNotNullList(finalRoleMenuDOS)) {
                var count = finalRoleMenuDOS.stream().filter(st -> st.getMenuId().compareTo(s.getId()) == 0).count();
                if (count > 0) {
                    r.setChecked(true);
                }
            }
            return null;
        });
        return success(iBaseMenuTrees);
    }

    private List<PMenuTreeVm> getMenuTree(UserVo userVo, QMenuListVo qMenuListVo) {
        List<PMenuTreeVm> pMenuTreeVms = menuMapper.getAllMenu(userVo, qMenuListVo);
        List<PMenuTreeVm> iBaseMenuTrees = TreeUtil.buildTree(pMenuTreeVms,null);
        return iBaseMenuTrees;
    }
}
